cmake_minimum_required(VERSION 3.12)

project(nndeploy)

ENABLE_LANGUAGE(ASM C CXX)

set(NNDEPLOY_MAJOR_VERSION 2)
set(NNDEPLOY_MINOR_VERSION 0)
set(NNDEPLOY_PATCH_VERSION 0)
set(NNDEPLOY_BUILD_VERSION 0)
set(NNDEPLOY_VERSION "${NNDEPLOY_MAJOR_VERSION}.${NNDEPLOY_MINOR_VERSION}.${NNDEPLOY_PATCH_VERSION}.${NNDEPLOY_BUILD_VERSION}")

message(STATUS "CMAKE BEIGIN. NNDEPLOY_VERSION: ${NNDEPLOY_VERSION}")

include(cmake/util.cmake)
include(cmake/summary.cmake)

if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/config.cmake)
  include(${CMAKE_CURRENT_BINARY_DIR}/config.cmake)
endif()

# framework
nndeploy_option(ENABLE_NNDEPLOY_BUILD_SHARED "ENABLE_NNDEPLOY_BUILD_SHARED" ON)
nndeploy_option(ENABLE_NNDEPLOY_SYMBOL_HIDE "ENABLE_NNDEPLOY_SYMBOL_HIDE" OFF)
nndeploy_option(ENABLE_NNDEPLOY_COVERAGE "ENABLE_NNDEPLOY_COVERAGE" OFF)
nndeploy_option(ENABLE_NNDEPLOY_CXX11_ABI "ENABLE_NNDEPLOY_CXX11_ABI" OFF)
nndeploy_option(ENABLE_NNDEPLOY_CXX14_ABI "ENABLE_NNDEPLOY_CXX14_ABI" OFF)
nndeploy_option(ENABLE_NNDEPLOY_CXX17_ABI "ENABLE_NNDEPLOY_CXX17_ABI" ON)
nndeploy_option(ENABLE_NNDEPLOY_CXX20_ABI "ENABLE_NNDEPLOY_CXX20_ABI" OFF)
nndeploy_option(ENABLE_NNDEPLOY_OPENMP "ENABLE_NNDEPLOY_OPENMP" OFF)
nndeploy_option(ENABLE_NNDEPLOY_ADDRESS_SANTIZER "ENABLE_NNDEPLOY_ADDRESS_SANTIZER" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DOCS "ENABLE_NNDEPLOY_DOCS" OFF)
nndeploy_option(ENABLE_NNDEPLOY_TIME_PROFILER "ENABLE_NNDEPLOY_TIME_PROFILER" ON)
nndeploy_option(ENABLE_NNDEPLOY_OPENCV "ENABLE_NNDEPLOY_OPENCV" OFF)
nndeploy_option(ENABLE_NNDEPLOY_RAPIDJSON "ENABLE_NNDEPLOY_RAPIDJSON" ON)

# # base
nndeploy_option(ENABLE_NNDEPLOY_BASE "ENABLE_NNDEPLOY_BASE" ON)

# # thread
nndeploy_option(ENABLE_NNDEPLOY_THREAD_POOL "ENABLE_NNDEPLOY_THREAD_POOL" ON)

# # cryption
nndeploy_option(ENABLE_NNDEPLOY_CRYPTION "ENABLE_NNDEPLOY_CRYPTION" OFF)

# # device
nndeploy_option(ENABLE_NNDEPLOY_DEVICE "ENABLE_NNDEPLOY_DEVICE" ON)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_CPU "ENABLE_NNDEPLOY_DEVICE_CPU" ON)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_ARM "ENABLE_NNDEPLOY_DEVICE_ARM" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_X86 "ENABLE_NNDEPLOY_DEVICE_X86" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_RISC_V "ENABLE_NNDEPLOY_DEVICE_RISC_V" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_CUDA "ENABLE_NNDEPLOY_DEVICE_CUDA" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_CUDNN "ENABLE_NNDEPLOY_DEVICE_CUDNN" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_ROCM "ENABLE_NNDEPLOY_DEVICE_ROCM" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_SYCL "ENABLE_NNDEPLOY_DEVICE_SYCL" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_OPENCL "ENABLE_NNDEPLOY_DEVICE_OPENCL" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_OPENGL "ENABLE_NNDEPLOY_DEVICE_OPENGL" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_METAL "ENABLE_NNDEPLOY_DEVICE_METAL" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_VULKAN "ENABLE_NNDEPLOY_DEVICE_VULKAN" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_HEXAGON "ENABLE_NNDEPLOY_DEVICE_HEXAGON" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_MTK_VPU "ENABLE_NNDEPLOY_DEVICE_MTK_VPU" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_ASCEND_CL "ENABLE_NNDEPLOY_DEVICE_ASCEND_CL" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_APPLE_NPU "ENABLE_NNDEPLOY_DEVICE_APPLE_NPU" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_RK_NPU "ENABLE_NNDEPLOY_DEVICE_RK_NPU" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_QUALCOMM_NPU "ENABLE_NNDEPLOY_DEVICE_QUALCOMM_NPU" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_MTK_NPU "ENABLE_NNDEPLOY_DEVICE_MTK_NPU" OFF)
nndeploy_option(ENABLE_NNDEPLOY_DEVICE_SOPHON_NPU "ENABLE_NNDEPLOY_DEVICE_SOPHON_NPU" OFF)

# # ir
nndeploy_option(ENABLE_NNDEPLOY_IR "ENABLE_NNDEPLOY_IR" ON)
nndeploy_option(ENABLE_NNDEPLOY_IR_ONNX "ENABLE_NNDEPLOY_IR_ONNX" OFF)

# # op
nndeploy_option(ENABLE_NNDEPLOY_OP "ENABLE_NNDEPLOY_OP" ON)
nndeploy_option(ENABLE_NNDEPLOY_OP_ASCEND_C "ENABLE_NNDEPLOY_OP_ASCEND_C" OFF)

# # net
nndeploy_option(ENABLE_NNDEPLOY_NET "ENABLE_NNDEPLOY_NET" ON)

# # inference
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE "ENABLE_NNDEPLOY_INFERENCE" ON)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_DEFAULT "ENABLE_NNDEPLOY_INFERENCE_DEFAULT" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_TENSORRT "ENABLE_NNDEPLOY_INFERENCE_TENSORRT" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_OPENVINO "ENABLE_NNDEPLOY_INFERENCE_OPENVINO" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_COREML "ENABLE_NNDEPLOY_INFERENCE_COREML" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_TFLITE "ENABLE_NNDEPLOY_INFERENCE_TFLITE" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_ONNXRUNTIME "ENABLE_NNDEPLOY_INFERENCE_ONNXRUNTIME" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_NCNN "ENABLE_NNDEPLOY_INFERENCE_NCNN" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_TNN "ENABLE_NNDEPLOY_INFERENCE_TNN" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_MNN "ENABLE_NNDEPLOY_INFERENCE_MNN" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_TVM "ENABLE_NNDEPLOY_INFERENCE_TVM" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_PADDLELITE "ENABLE_NNDEPLOY_INFERENCE_PADDLELITE" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_RKNN_TOOLKIT_1 "ENABLE_NNDEPLOY_INFERENCE_RKNN_TOOKIT_1" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_RKNN_TOOLKIT_2 "ENABLE_NNDEPLOY_INFERENCE_RKNN_TOOKIT_2" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_ASCEND_CL "ENABLE_NNDEPLOY_INFERENCE_ASCEND_CL" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_SNPE "ENABLE_NNDEPLOY_INFERENCE_SNPE" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_QNN "ENABLE_NNDEPLOY_INFERENCE_QNN" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_SOPHON "ENABLE_NNDEPLOY_INFERENCE_SOPHON" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_TORCH "ENABLE_NNDEPLOY_INFERENCE_TORCH" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_TENSORFLOW "ENABLE_NNDEPLOY_INFERENCE_TENSORFLOW" OFF)
nndeploy_option(ENABLE_NNDEPLOY_INFERENCE_NEUROPILOT "ENABLE_NNDEPLOY_INFERENCE_NEUROPILOT" OFF)

# # dag
nndeploy_option(ENABLE_NNDEPLOY_DAG "ENABLE_NNDEPLOY_DAG" ON)

# plugin
nndeploy_option(ENABLE_NNDEPLOY_PLUGIN "ENABLE_NNDEPLOY_PLUGIN" OFF)

# test
nndeploy_option(ENABLE_NNDEPLOY_TEST "ENABLE_NNDEPLOY_TEST" OFF)

# demo
nndeploy_option(ENABLE_NNDEPLOY_DEMO "ENABLE_NNDEPLOY_DEMO" OFF)

# python
nndeploy_option(ENABLE_NNDEPLOY_PYTHON "ENABLE_NNDEPLOY_PYTHON" OFF)

# print option
print_summary()

# 生成compile_commands.json文件
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set
set(ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

# folders
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# install path
set(NNDEPLOY_INSTALL_PATH ${ROOT_PATH}/build/install)

if(ENABLE_NNDEPLOY_BUILD_SHARED)
  set(NNDEPLOY_INSTALL_TYPE LIBRARY)
else()
  set(NNDEPLOY_INSTALL_TYPE ARCHIVE)
endif()

set(CMAKE_INSTALL_PREFIX ${NNDEPLOY_INSTALL_PATH})
set(NNDEPLOY_INSTALL_LIB_PATH ${NNDEPLOY_INSTALL_PATH}/lib)
set(NNDEPLOY_INSTALL_BIN_PATH ${NNDEPLOY_INSTALL_PATH}/bin)

set(EXECUTABLE_OUTPUT_PATH ${ROOT_PATH}/build)

# build type
if(ENABLE_NNDEPLOY_BUILD_SHARED)
  set(NNDEPLOY_LIB_TYPE SHARED)
else()
  set(NNDEPLOY_LIB_TYPE STATIC)
endif()

# define
if(CMAKE_BUILD_TYPE MATCHES "Debug")
  add_definitions(-DNNDEPLOY_DEBUG)
endif()

if(${ENABLE_NNDEPLOY_DEVICE_ARM} MATCHES "OFF")
else()
  add_definitions(-DENABLE_NNDEPLOY_DEVICE_ARM)
endif()

if(${ENABLE_NNDEPLOY_DEVICE_X86} MATCHES "OFF")
else()
  add_definitions(-DENABLE_NNDEPLOY_DEVICE_X86)
endif()

if(${ENABLE_NNDEPLOY_TIME_PROFILER} MATCHES "OFF")
else()
  add_definitions(-DENABLE_NNDEPLOY_TIME_PROFILER)
endif()

if(${ENABLE_NNDEPLOY_OPENCV} MATCHES "OFF")
else()
  add_definitions(-DENABLE_NNDEPLOY_OPENCV)
endif()

# general
set(NNDEPLOY_LIB_PREFIX "lib")
set(NNDEPLOY_LIB_SUFFIX ".so")

if(CMAKE_SYSTEM_NAME MATCHES "^Android")
  set(SYSTEM.Android 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Linux")
  set(SYSTEM.Linux 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Darwin")
  set(SYSTEM.Darwin 1)
  set(NNDEPLOY_LIB_SUFFIX ".dylib")
elseif(CMAKE_SYSTEM_NAME MATCHES "^iOS")
  set(SYSTEM.iOS 1)
elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows")
  set(SYSTEM.Windows 1)
  set(NNDEPLOY_LIB_PREFIX "")
  set(NNDEPLOY_LIB_SUFFIX ".lib")
endif()

if(SYSTEM.Windows AND ENABLE_NNDEPLOY_BUILD_SHARED)
  add_definitions(-DENABLE_NNDEPLOY_BUILDING_DLL)
endif()

if(!SYSTEM.Windows)
  # you must have return sentence for un-void function
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type")
endif()

if(UNIX)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()

if(ENABLE_NNDEPLOY_OPENMP)
  FIND_PACKAGE(OpenMP REQUIRED)

  if(OPENMP_FOUND)
    add_definitions(-DENABLE_NNDEPLOY_OPENMP)

    if(MSVC)
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp")
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp")
    else()
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
      include_directories(${OpenMP_C_INCLUDE_DIRS} ${OpenMP_CXX_INCLUDE_DIRS})

      if(${ANDROID_NDK_MAJOR})
        if(${ANDROID_NDK_MAJOR} GREATER 20)
        else()
          link_libraries(${OpenMP_C_LIBRARIES} ${OpenMP_CXX_LIBRARIES})
        endif()
      else()
        link_libraries(${OpenMP_C_LIBRARIES} ${OpenMP_CXX_LIBRARIES})
      endif()
    endif()
  else()
    error("OpenMP Not Found.")
  endif()
endif()

if(ENABLE_NNDEPLOY_CXX20_ABI)
  set(CMAKE_CXX_STANDARD 20)
  set(ENABLE_NNDEPLOY_CXX17_ABI OFF)
  set(ENABLE_NNDEPLOY_CXX14_ABI OFF)
  set(ENABLE_NNDEPLOY_CXX11_ABI OFF)
endif()

if(ENABLE_NNDEPLOY_CXX17_ABI)
  set(CMAKE_CXX_STANDARD 17)
  set(ENABLE_NNDEPLOY_CXX14_ABI OFF)
  set(ENABLE_NNDEPLOY_CXX11_ABI OFF)
endif()

if(ENABLE_NNDEPLOY_CXX14_ABI)
  if(ENABLE_NNDEPLOY_PLUGIN_TOKENIZER_CPP)
    set(CMAKE_CXX_STANDARD 17)
  else()
    set(CMAKE_CXX_STANDARD 14)
    set(ENABLE_NNDEPLOY_CXX11_ABI OFF)
  endif()
endif()

if(ENABLE_NNDEPLOY_CXX11_ABI)
  if(ENABLE_NNDEPLOY_PLUGIN_TOKENIZER_CPP)
    set(CMAKE_CXX_STANDARD 17)
  else()
    set(CMAKE_CXX_STANDARD 11)
  endif()
endif()

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

if(ENABLE_NNDEPLOY_DEVICE_METAL OR ENABLE_NNDEPLOY_DEVICE_APPLE_NPU)
  # compile the file according to file type
  # add_compile_nndeploy_options(-x objective-c++)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc -Wno-shorten-64-to-32")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -Wno-shorten-64-to-32 -Wno-null-character")
  set(CMAKE_OBJCXX_FLAGS "${CMAKE_OBJCXX_FLAGS} -x objective-c++ -fobjc-arc -Wno-shorten-64-to-32 -Wno-null-character")
endif()

if(SYSTEM.Linux AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm" AND ANDROID_API_LEVAL)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_C99_MATH_TR1")
  add_definitions(-D__ANDROID_API__=${ANDROID_API_LEVAL})
endif()

if(ENABLE_NNDEPLOY_COVERAGE)
  if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
  elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -coverage -fprofile-arcs -ftest-coverage")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage -lgcov")
  endif()
endif()

if(ENABLE_NNDEPLOY_ADDRESS_SANTIZER)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
endif()

# Check endianness
include(TestBigEndian)
test_big_endian(NNDEPLOY_BIG_ENDIAN)
if(NNDEPLOY_BIG_ENDIAN)
  set(NNDEPLOY_CMAKE_LITTLE_ENDIAN 0)
else()
  set(NNDEPLOY_CMAKE_LITTLE_ENDIAN 1)
endif()

set(ENABLE_NNDEPLOY_SAFETENSORS_CPP OFF)
if(ENABLE_NNDEPLOY_IR)
  set(ENABLE_NNDEPLOY_SAFETENSORS_CPP ON)
  add_definitions(-DENABLE_NNDEPLOY_SAFETENSORS_CPP)
  if(ENABLE_NNDEPLOY_IR_ONNX)
    set(ENABLE_NNDEPLOY_PROTOBUF ON)
    set(ENABLE_NNDEPLOY_ONNX ON)
  endif()
endif()

if(ENABLE_NNDEPLOY_PLUGIN_TOKENIZER_CPP)
  # set(ENABLE_NNDEPLOY_PROTOBUF ON)
endif()

# include
include_directories(${ROOT_PATH}/framework/include)
include_directories(${ROOT_PATH}/framework/source)
include_directories(third_party)

# make
set(NNDEPLOY_FRAMEWORK_SOURCE)
set(NNDEPLOY_FRAMEWORK_OBJECT)
set(NNDEPLOY_FRAMEWORK_BINARY nndeploy_framework)
set(NNDEPLOY_FRAMEWORK_DIRECTORY nndeploy_framework)
set(NNDEPLOY_DEPEND_LIBRARY)
set(NNDEPLOY_SYSTEM_LIBRARY)
set(NNDEPLOY_THIRD_PARTY_LIBRARY)
set(NNDEPLOY_PLUGIN_THIRD_PARTY_LIBRARY)
set(NNDEPLOY_TEST_THIRD_PARTY_LIBRARY)
set(NNDEPLOY_DEMO_DEPEND_LIBRARY)
set(NNDEPLOY_DEMO_SYSTEM_LIBRARY)
set(NNDEPLOY_DEMO_THIRD_PARTY_LIBRARY)

# nndeploy third party lib
include(${ROOT_PATH}/cmake/nndeploy.cmake)

# nndeploy framework
set(FRAMEWORK_ROOT_PATH ${ROOT_PATH}/framework)

# nndeploy source
# # attention GLOB or GLOB_RECURSE
file(GLOB NNDEPLOY_FRAMEWORK_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/*.cc"
    )

if(ENABLE_NNDEPLOY_BASE)
  file(GLOB_RECURSE BASE_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/base/*.h"
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/base/*.hpp"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/base/*.cc"
  )
  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${BASE_SOURCE})
endif()

if(ENABLE_NNDEPLOY_THREAD_POOL)
  file(GLOB_RECURSE THREAD_POOL_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/thread_pool/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/thread_pool/*.cc"
  )
  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${THREAD_POOL_SOURCE})
endif()

if(ENABLE_NNDEPLOY_CRYPTION)
  file(GLOB CRYPTION_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/cryption/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/cryption/*.cc"
  )
  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${CRYPTION_SOURCE})
endif()

if(ENABLE_NNDEPLOY_DEVICE)
  file(GLOB DEVICE_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/device/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/device/*.cc"
  )

  if(ENABLE_NNDEPLOY_DEVICE_CPU)
    file(GLOB_RECURSE DEVICE_CPU_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/device/cpu/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/device/cpu/*.cc"
    )
    set(DEVICE_SOURCE ${DEVICE_SOURCE} ${DEVICE_CPU_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_X86)
    file(GLOB_RECURSE DEVICE_X86_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/device/x86/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/device/x86/*.cc"
    )
    set(DEVICE_SOURCE ${DEVICE_SOURCE} ${DEVICE_X86_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_ARM)
    file(GLOB_RECURSE DEVICE_ARM_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/device/arm/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/device/arm/*.cc"
    )
    set(DEVICE_SOURCE ${DEVICE_SOURCE} ${DEVICE_ARM_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_CUDA)
    file(GLOB_RECURSE DEVICE_CUDA_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/device/cuda/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/device/cuda/*.cc"
    )
    set(DEVICE_SOURCE ${DEVICE_SOURCE} ${DEVICE_CUDA_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_ASCEND_CL)
    file(GLOB_RECURSE DEVICE_ASCEND_CL_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/device/ascend_cl/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/device/ascend_cl/*.cc"
    )
    set(DEVICE_SOURCE ${DEVICE_SOURCE} ${DEVICE_ASCEND_CL_SOURCE})
  endif()

  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${DEVICE_SOURCE})
endif()

if(ENABLE_NNDEPLOY_OP)
  file(GLOB OP_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/op/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/*.cc"
  )

  # if(ENABLE_NNDEPLOY_DEVICE_CPU)
  #   file(GLOB_RECURSE OP_CPU_SOURCE
  #     "${FRAMEWORK_ROOT_PATH}/include/nndeploy/op/cpu/*.h"
  #     "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/cpu/*.cc"
  #   )
  #   set(OP_SOURCE ${OP_SOURCE} ${OP_CPU_SOURCE})
  # endif()

  if(ENABLE_NNDEPLOY_DEVICE_X86)
    file(GLOB_RECURSE OP_X86_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/op/x86/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/x86/*.cc"
    )
    set(OP_SOURCE ${OP_SOURCE} ${OP_X86_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_ARM)
    file(GLOB_RECURSE OP_ARM_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/op/arm/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/arm/*.cc"
    )
    set(OP_SOURCE ${OP_SOURCE} ${OP_ARM_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_CUDA)
    file(GLOB_RECURSE OP_CUDA_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/op/cuda/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/cuda/*.cc"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/*.cu"
    )
    set(OP_SOURCE ${OP_SOURCE} ${OP_CUDA_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_DEVICE_ASCEND_CL)
    file(GLOB OP_ASCEND_CL_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/op/ascend_cl/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/ascend_cl/*.cc"
    )
    set(OP_SOURCE ${OP_SOURCE} ${OP_ASCEND_CL_SOURCE})
    if (ENABLE_NNDEPLOY_OP_ASCEND_C)
      add_definitions(-DENABLE_NNDEPLOY_OP_ASCEND_C)
      file(GLOB_RECURSE OP_ASCEND_C_SOURCE
          "${FRAMEWORK_ROOT_PATH}/source/nndeploy/op/ascend_cl/ascend_c/*.cc"
      )
      ascendc_library(nndeploy_framework_ascend_c_kernels STATIC ${OP_ASCEND_C_SOURCE})
      set(NNDEPLOY_THIRD_PARTY_LIBRARY ${NNDEPLOY_THIRD_PARTY_LIBRARY} nndeploy_framework_ascend_c_kernels)  
    endif()
  endif()
  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${OP_SOURCE})
endif()

if(ENABLE_NNDEPLOY_IR)
  file(GLOB IR_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/ir/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/ir/*.cc"
  )

  if(ENABLE_NNDEPLOY_IR_ONNX)
    file(GLOB_RECURSE IR_ONNX_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/ir/onnx/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/ir/onnx/*.cc"
    )
    set(IR_SOURCE ${IR_SOURCE} ${IR_ONNX_SOURCE})
  endif()

  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${IR_SOURCE})
endif()

if(ENABLE_NNDEPLOY_NET)
  file(GLOB_RECURSE NET_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/net/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/net/*.cc"
  )

  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${NET_SOURCE})
endif()

if(ENABLE_NNDEPLOY_INFERENCE)
  file(GLOB INFERENCE_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/*.h"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/*.cc"
  )

  if(ENABLE_NNDEPLOY_INFERENCE_DEFAULT)
    file(GLOB_RECURSE INFERENCE_DEFAULT_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/default/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/default/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_DEFAULT_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_TENSORRT)
    file(GLOB_RECURSE INFERENCE_TENSORRT_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/tensorrt/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/tensorrt/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_TENSORRT_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_TNN)
    file(GLOB_RECURSE INFERENCE_TNN_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/tnn/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/tnn/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_TNN_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_MNN)
    file(GLOB_RECURSE INFERENCE_MNN_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/mnn/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/mnn/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_MNN_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_OPENVINO)
    file(GLOB_RECURSE INFERENCE_OPENVINO_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/openvino/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/openvino/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_OPENVINO_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_COREML)
    file(GLOB_RECURSE INFERENCE_COREML_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/coreml/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/coreml/*.cc"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/coreml/*.mm"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_COREML_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_ONNXRUNTIME)
    file(GLOB_RECURSE INFERENCE_ONNXRUNTIME_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/onnxruntime/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/onnxruntime/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_ONNXRUNTIME_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_TFLITE)
    file(GLOB_RECURSE INFERENCE_TFLITE_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/tflite/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/tflite/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_TFLITE_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_NCNN)
    file(GLOB_RECURSE INFERENCE_NCNN_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/ncnn/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/ncnn/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_NCNN_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_PADDLELITE)
    file(GLOB_RECURSE INFERENCE_PADDLELITE_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/paddlelite/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/paddlelite/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_PADDLELITE_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_RKNN)
    file(GLOB_RECURSE INFERENCE_RKNN_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/rknn/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/rknn/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_RKNN_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_ASCEND_CL)
    file(GLOB_RECURSE INFERENCE_ASCEND_CL_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/ascend_cl/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/ascend_cl/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_ASCEND_CL_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_SNPE)
    file(GLOB_RECURSE INFERENCE_SNPE_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/snpe/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/snpe/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_SNPE_SOURCE})
  endif()

  if(ENABLE_NNDEPLOY_INFERENCE_TVM)
    file(GLOB_RECURSE INFERENCE_TVM_SOURCE
      "${FRAMEWORK_ROOT_PATH}/include/nndeploy/inference/tvm/*.h"
      "${FRAMEWORK_ROOT_PATH}/source/nndeploy/inference/tvm/*.cc"
    )
    set(INFERENCE_SOURCE ${INFERENCE_SOURCE} ${INFERENCE_TVM_SOURCE})
  endif()

  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${INFERENCE_SOURCE})
endif()

if(ENABLE_NNDEPLOY_DAG)
  file(GLOB_RECURSE DAG_SOURCE
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/dag/*.h"
    "${FRAMEWORK_ROOT_PATH}/include/nndeploy/dag/*.hpp"
    "${FRAMEWORK_ROOT_PATH}/source/nndeploy/dag/*.cc"
  )
  set(NNDEPLOY_FRAMEWORK_SOURCE ${NNDEPLOY_FRAMEWORK_SOURCE} ${DAG_SOURCE})
endif()

# nndeploy
# # TARGET
add_library(${NNDEPLOY_FRAMEWORK_BINARY} ${NNDEPLOY_LIB_TYPE} ${NNDEPLOY_FRAMEWORK_SOURCE} ${NNDEPLOY_FRAMEWORK_OBJECT})

# # DIRECTORY
set_property(TARGET ${NNDEPLOY_FRAMEWORK_BINARY} PROPERTY FOLDER ${NNDEPLOY_FRAMEWORK_DIRECTORY})

# # DEPEND_LIBRARY
target_link_libraries(${NNDEPLOY_FRAMEWORK_BINARY} ${NNDEPLOY_DEPEND_LIBRARY})
message(STATUS "NNDEPLOY_DEPEND_LIBRARY: ${NNDEPLOY_DEPEND_LIBRARY}")

# # SYSTEM_LIBRARY
target_link_libraries(${NNDEPLOY_FRAMEWORK_BINARY} ${NNDEPLOY_SYSTEM_LIBRARY})
message(STATUS "NNDEPLOY_SYSTEM_LIBRARY: ${NNDEPLOY_SYSTEM_LIBRARY}")

# # THIRD_PARTY_LIBRARY
target_link_libraries(${NNDEPLOY_FRAMEWORK_BINARY} ${NNDEPLOY_THIRD_PARTY_LIBRARY})
message(STATUS "NNDEPLOY_THIRD_PARTY_LIBRARY: ${NNDEPLOY_THIRD_PARTY_LIBRARY}")

# # install
if(SYSTEM.Windows)
  install(TARGETS ${NNDEPLOY_FRAMEWORK_BINARY} ${NNDEPLOY_INSTALL_TYPE} DESTINATION ${NNDEPLOY_INSTALL_PATH})
else()
  install(TARGETS ${NNDEPLOY_FRAMEWORK_BINARY} ${NNDEPLOY_INSTALL_TYPE} DESTINATION ${NNDEPLOY_INSTALL_LIB_PATH})
endif()

# plugin
if(ENABLE_NNDEPLOY_PLUGIN)
  include(${ROOT_PATH}/plugin/config.cmake)
endif()

# GFLAGS
set(ENABLE_NNDEPLOY_GFLAGS OFF)

if(ENABLE_NNDEPLOY_TEST)
  set(ENABLE_NNDEPLOY_GFLAGS ON)
endif()

if(ENABLE_NNDEPLOY_DEMO)
  set(ENABLE_NNDEPLOY_GFLAGS ON)
endif()

if(ENABLE_NNDEPLOY_GFLAGS)
  if(APPLE)
    find_package(gflags QUIET)
    if(gflags_FOUND)
      message(STATUS "gflags library found:")
      message(STATUS "    version: ${gflags_VERSION}")
      message(STATUS "    include path: ${gflags_INCLUDE_DIRS}")
      message(STATUS "    libraries: ${gflags_LIBRARIES}")

      include_directories(${gflags_INCLUDE_DIRS})
      set(NNDEPLOY_THIRD_PARTY_LIBRARY ${NNDEPLOY_THIRD_PARTY_LIBRARY} ${gflags_LIBRARIES})
    else()
      message(FATAL_ERROR "gflags not found in system. brew install gflags or source build gflafs")
    endif()
  else()
    add_subdirectory(third_party/gflags)
    get_target_property(GFLAGS_INCLUDE_DIRS gflags INTERFACE_INCLUDE_DIRECTORIES)
    include_directories(BEFORE "${GFLAGS_INCLUDE_DIRS}")
  endif()
endif()

# test
if(ENABLE_NNDEPLOY_TEST)
  add_subdirectory(third_party/googletest) # this does make the build slow. I wonder if there is a way to avoid this. 
  include(${ROOT_PATH}/test/config.cmake)
endif()

# demo
if(ENABLE_NNDEPLOY_DEMO)
  include(${ROOT_PATH}/demo/config.cmake)
endif()

# python
if(ENABLE_NNDEPLOY_PYTHON)
  include(${ROOT_PATH}/python/config.cmake)
endif()

message(STATUS "CMAKE END. NNDEPLOY_VERSION: ${NNDEPLOY_VERSION}")
